#include "keywordlib.h"
#include "databasetool.h"
#include <iostream>
#define DBNAME "keywordlibs.db"
#define SPLIT  '$'
#define MAXCOUNT 63

KeyWordLib* KeyWordLib::_instance=nullptr;

KeyWordLib* KeyWordLib::GetInstance(QObject *parent)
{
    if(KeyWordLib::_instance==nullptr)
        KeyWordLib::_instance=new KeyWordLib(parent);
    return KeyWordLib::_instance;
}


KeyWordLib::KeyWordLib(QObject *parent) :
    QObject(parent),
    hashtable(MAXCOUNT,-1)
{
    bool ret=Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);
    if(!ret)
        std::cout<<"关键词库启动失败"<<std::endl;
    else{
        std::cout<<"数据库启动成功"<<std::endl;
        InitDate();
    }
}

KeyWordLib::~KeyWordLib()
{

}

void KeyWordLib::InitDate()
{
    /*
     * 1.初始化所有词库编号
     * ２.初始化部分词库编号
*/
    this->maxindex=-1;
    if(!Yzty::DataBaseTool::GetInsatnce()->Execute("select TypeId,TypeName from KeyWordType"))
    {
        std::cout<<"初始化失败"<<std::endl;
    }else
    {
        QVector<QStringList>&& temp=Yzty::DataBaseTool::GetInsatnce()->GetResult();
//        while(query.next())
//        {
//            int id=query.value(0).toInt();
//            QString name=query.value(1).toString();
//            typenames[getindex(id)]=name;
//            maxindex=qMax(maxindex,id);
//        }
        for(QStringList& item:temp){
            typenames[getindex(item[0].toInt())]=item[1];
            maxindex=qMax(maxindex,item[0].toInt());
        }
    }
}

bool KeyWordLib::AddKeyWordLib(const QString& TypeName, const QStringList& words)
{
    Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);
    if(!Yzty::DataBaseTool::GetInsatnce()->IsContain(DBNAME))
        Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);

    bool flag=false;

    Yzty::DataBaseTool::GetInsatnce()->Transaction();       //开启事务

    if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("insert into KeyWordType values(%1,'%2')")
                                                   .arg(maxindex+1).arg(TypeName)))
    {
        std::cout<<"词库类型插入失败"<<std::endl;
        Yzty::DataBaseTool::GetInsatnce()->RollBack();
    }else
    {
        QString temp=words.join(QChar(SPLIT));
        if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("insert into KeyWords values(%1,'%2')").arg(maxindex+1).arg(temp)))
        {
            std::cout<<"关键词插入失败"<<std::endl;
            Yzty::DataBaseTool::GetInsatnce()->RollBack();
        }else
        {
            Yzty::WordLibCode code=getindex(maxindex+1);
            typenames[code]=TypeName;
            word_cache[code]=words.toVector();
            Yzty::DataBaseTool::GetInsatnce()->Commit();
            flag=true;
            maxindex++;
        }
    }
    return flag;
}

bool KeyWordLib::DeleteWordLib(Yzty::WordLibCode code)
{
    Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);
    if(!Yzty::DataBaseTool::GetInsatnce()->IsContain(DBNAME))
        Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);

    bool flag=false;

    int index=-1,hind=-1;
    for(int i=0;i<63;++i)
        if((1<<i)==code)
        {
            index=hashtable[i];
            hind=i;
        }

    Yzty::DataBaseTool::GetInsatnce()->Transaction();

    if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("delete from KeyWordType where TypeId=%1").arg(index)))
    {
        std::cout<<"关键词库删除失败"<<std::endl;
        Yzty::DataBaseTool::GetInsatnce()->RollBack();
    }else
    {
        if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("delete from KeyWords where TypeId=%1").arg(index)))
        {
            std::cout<<"关键词库删除失败"<<std::endl;
            Yzty::DataBaseTool::GetInsatnce()->RollBack();
        }else
        {
            hashtable[hind]=-1;
            typenames.remove(code);
            Yzty::DataBaseTool::GetInsatnce()->Commit();
            flag=true;
        }
    }
    return flag;
}


bool KeyWordLib::ModiftyWord(Yzty::WordLibCode code, int wordindex, const QString &word)
{
    Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);
    bool flag=false;

    Yzty::DataBaseTool::GetInsatnce()->Transaction();

    QString pre=word_cache[code][wordindex];
    word_cache[code][wordindex]=word;

    QString temp=QStringList(word_cache[code].toList()).join(SPLIT);

    if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("update KeyWords set Words='%1' where TypeId=%2").arg(temp).arg(code)))
    {
        word_cache[code][wordindex]=pre;
        std::cout<<"关键词修改失败"<<std::endl;
        Yzty::DataBaseTool::GetInsatnce()->RollBack();
    }else
    {
        flag=true;
        Yzty::DataBaseTool::GetInsatnce()->Commit();
    }
    return flag;
}

bool KeyWordLib::DeleteWord(Yzty::WordLibCode code, int wordindex)
{
    Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);
    bool flag=false;

    QString pre=word_cache[code][wordindex];
    word_cache[code].remove(wordindex);
    QString temp=QStringList(word_cache[code].toList()).join(SPLIT);

    if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("update KeyWords set Words='%1' where TypeId=%2").arg(temp).arg(code)))
    {
        word_cache[code].insert(wordindex,pre);
        std::cout<<"关键词删除失败"<<std::endl;
        Yzty::DataBaseTool::GetInsatnce()->RollBack();
    }else
    {
        flag=true;
        Yzty::DataBaseTool::GetInsatnce()->Commit();
    }
    return flag;

}

QString KeyWordLib::GetWord(Yzty::WordLibCode code, int wordindex)
{
    if(word_cache.count(code)==0)
        CacheLack(code);
    return word_cache[code][wordindex];
}

QString KeyWordLib::GetLibName(Yzty::WordLibCode code)
{
    return typenames[code];
}

Yzty::WordLibCode KeyWordLib::getindex(int index)
{
    int key=index%MAXCOUNT;

    while(hashtable[key]!=-1&&hashtable[key]!=index)
        key=(key+1)%MAXCOUNT;
    hashtable[key]=index;
    return 1<<key;
}

const QVector<QString>& KeyWordLib::GetWordList(Yzty::WordLibCode code)
{
    if(word_cache.count(code)==0)
        CacheLack(code);
    return word_cache[code];
}

int KeyWordLib::GetKeyWordNums(Yzty::WordLibCode code)
{
    if(word_cache.count(code)==0)
        CacheLack(code);
    return word_cache[code].size();
}

void KeyWordLib::CacheLack(Yzty::WordLibCode code)
{
    Yzty::DataBaseTool::GetInsatnce()->SetDataBaseName(DBNAME);
    for(int i=0;i<MAXCOUNT;++i)
    {
        if((code>>i)&1)
        {
            std::cout<<"hashvalue: "<<hashtable[i]<<std::endl;
            if(!Yzty::DataBaseTool::GetInsatnce()->Execute(QString("select Words from KeyWords where TypeId=%1").arg(hashtable[i])))
            {
                std::cout<<"关键词缺少异常"<<std::endl;
                exit(-1);
            }else
            {
                QVector<QStringList>&& temp=Yzty::DataBaseTool::GetInsatnce()->GetResult();
//                while(query.next())
//                {
//                    word_cache[code]=query.value(0).toString().split(SPLIT).toVector();
//                }
                for(QStringList& item:temp)
                    word_cache[code]=item[0].split(SPLIT).toVector();
            }
        }
    }
}

const QMap<Yzty::WordLibCode,QString>& KeyWordLib::GetLibNameList()
{
    return typenames;
}

